local build = strjoin(" - ", GetBuildInfo())
local CLASSES = { 'DRUID','HUNTER','MAGE','PALADIN','PRIEST','ROGUE','SHAMAN','WARLOCK','WARRIOR','DEATHKNIGHT' }

local function checkdiffs(class, inspect)
	if select(5, GetAddOnInfo("Talented_Data")) then
		local messages = {}
		local function msg(s, ...)
			if s:find("%", 1, 1) then
				s = s:format(...)
			end
			table.insert(messages, s)
		end
		local function assert(v, ...)
			if not v then
				msg(...)
			end
		end
		if not IsAddOnLoaded("Talented_Data") then
			LoadAddOn("Talented_Data")
		end
		local source, dest = Talented_GatherDB[build][class], Talented_Data[class]
		assert(#source == #dest, "Different number of Talent Tabs for class %s %d => %d", class, #source, #dest)
		for tab = 1, math.min(#source, #dest) do
			local sinfo, dinfo = source[tab].info, dest[tab].info
			assert(sinfo.icon == dinfo.icon, "Tab %s:%d has a new icon %s => %s", class, tab, sinfo.icon, dinfo.icon)
			assert(sinfo.background == dinfo.background, "Tab %s:%d has a new background  %s => %s", class, tab, sinfo.background, dinfo.background)
			local name = GetTalentTabInfo(tab, inspect)
			assert(name == dinfo.name, "Tab %s:%d has a new name %s => %s", class, tab, name, dinfo.name)

			local stalents, dtalents = source[tab].talents, dest[tab].talents
			assert(#stalents == #dtalents, "Different number of talents for tab %s:%d %d => %d", class, tab, #stalents, #dtalents)
			for index = 1, math.min(#stalents, #dtalents) do
				local sinfo, dinfo = stalents[index].info, dtalents[index].info
				assert(sinfo.icon == dinfo.icon, "Talent %s:%d:%d has a new icon %s => %s", class, tab, index, sinfo.icon, dinfo.icon)
				assert(sinfo.row == dinfo.row, "Talent %s:%d:%d has a new row %d => %d", class, tab, index, sinfo.row, dinfo.row)
				assert(sinfo.column == dinfo.column, "Talent %s:%d:%d has a new column %d => %d", class, tab, index, sinfo.column, dinfo.column)
				assert(sinfo.ranks == dinfo.ranks, "Talent %s:%d:%d has a new ranks %d => %d", class, tab, index, sinfo.ranks, dinfo.ranks)
				assert(sinfo.exceptional == dinfo.exceptional, "Talent %s:%d:%d has a new exceptional %d => %d", class, tab, index, sinfo.exceptional, dinfo.exceptional)
				local name = GetTalentInfo(tab, index, inspect)
				assert(name == dinfo.name, "Talent %s:%d:%d has a new name %s => %s", class, tab, index, name, dinfo.name)
				assert(type(sinfo.prereqs) == type(dinfo.prereqs), "Talent %s:%d:%d has a different type of prereqs", class, tab, index)
				if type(sinfo.prereqs) == "table" and type(dinfo.prereqs) == "table" then
					assert(#sinfo.prereqs == #dinfo.prereqs, "Talent %s:%d:%d has a different number of prereqs", class, tab, index)
					for p = 1, math.min(#sinfo.prereqs, #dinfo.prereqs) do
						assert(sinfo.prereqs[p].row == dinfo.prereqs[p].row, "Prereq %s:%d:%d:%d has a new row", class, tab, index, p)
						assert(sinfo.prereqs[p].column == dinfo.prereqs[p].column, "Prereq %s:%d:%d:%d has a new row", class, tab, index, p)
					end
				end
			end
		end
		if #messages > 0 then
			DEFAULT_CHAT_FRAME:AddMessage("Talented_GatherData has detected differences !")
			DEFAULT_CHAT_FRAME:AddMessage("  ----------  ")
			for _, s in ipairs(messages) do
				DEFAULT_CHAT_FRAME:AddMessage(s)
			end
			DEFAULT_CHAT_FRAME:AddMessage("  ----------  ")
			Talented_GatherDB[build][class].differences = messages
		end
	end
end

local FillPrereqs = function (...)
	if select("#", ...) < 3 then return end
	local table = {}
	for i = 1, select("#", ...), 3 do
		local row, column = select(i, ...)
		table[#table + 1] = { row = row, column = column }
	end
	return table
end

local function GetClassTalentsInfo(class, inspect)
	local result = {}
	local count = GetNumTalentTabs(inspect)
	if count == 0 then return end
	for tab = 1, count do
		local icon, _, background = select(2, GetTalentTabInfo(tab, inspect))
		result[tab] = {
			info = {
				icon = icon,
				background = background,
			},
			talents = {}
		}
		local talents = result[tab].talents
		for index = 1, GetNumTalents(tab, inspect) do
			local icon, row, column, _, ranks, exceptional = select(2, GetTalentInfo(tab, index, inspect))
			talents[index] = {
				info = {
					icon = icon,
					row = row,
					column = column,
					ranks = ranks,
					exceptional = exceptional,
					prereqs = FillPrereqs(GetTalentPrereqs(tab, index, inspect)),
				},
			}
		end
	end
	Talented_GatherDB[build][class] = result
	checkdiffs(class, inspect)
	local missing = {}
	for _, c in ipairs(CLASSES) do
		if not Talented_GatherDB[build][c] then
			missing[#missing + 1] = c
		end
	end
	if #missing > 0 then
		DEFAULT_CHAT_FRAME:AddMessage("Talented_GatherDB is still missing the following classes: "..table.concat(missing, ", "))
	end
	return true
end

local f = CreateFrame"Frame"

function f:OnUpdate(elapsed)
	self.time = self.time - elapsed
	if self.time < 0 then
		self:UpdateTalents()
	end
end

function f:UpdateTalents()
	self:SetScript("OnUpdate", nil)
	if GetClassTalentsInfo(select(2, UnitClass("player")), nil) then
		self:Hide()
	else
		self.time = 1
		self:SetScript("OnUpdate", self.OnUpdate)
	end
end

function f:PLAYER_LOGIN()
	self:UpdateTalents()
end

function f:ADDON_LOADED(addon)
	if addon == "Talented_GatherData" then
		Talented_GatherDB = Talented_GatherDB or {}
		Talented_GatherDB.latest = build
		Talented_GatherDB[build] = Talented_GatherDB[build] or {}
	end
end

function f:INSPECT_TALENT_READY()
	local unit = InspectFrame and InspectFrame.unit
	if not unit then return end
	local class = select(2, UnitClass(unit))
	assert(GetClassTalentsInfo(class, true))
end

f:RegisterEvent"PLAYER_LOGIN"
f:RegisterEvent"ADDON_LOADED"
f:RegisterEvent"INSPECT_TALENT_READY"

f:SetScript("OnEvent", function (self, event, ...)
	local handler = self[event]
	if type(handler) == "function" then
		handler(self, ...)
	end
end)
